home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 2
/
Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso
/
Aminet
/
util
/
gnu
/
oleo_src.lha
/
src
/
io_disp.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-08-31
|
49KB
|
2,479 lines
/* Copyright (C) 1990 Free Software Foundation, Inc.
This file is part of Oleo, the GNU Spreadsheet.
Oleo is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
Oleo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Oleo; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "funcdef.h"
#include <fcntl.h>
#include <errno.h>
#include <ctype.h>
#ifdef __TURBOC__
#include <conio.h>
#include <stdarg.h>
#include <stdio.h>
#define COLS 80
#define LINES 24
#define endwin() clrscr()
#define initscr()
#define scrollok(x,y)
#define cbreak()
#define noecho()
#define nonl()
#define nl()
#define refresh()
#define mvaddch(r,c,ch) move(r,c),addch(ch)
#define mvaddstr(r,c,st) move(r,c),addstr(st)
#define clear() clrscr()
#define clrtoeol() clreol()
#define addstr(str) cputs(str)
#define addch(ch) putch(ch)
#define move(y,x) gotoxy(x+1,y+1)
#define getyx(nul,yy,xx) yy=wherey()-1,xx=wherex()-1
#define delch() movetext(col+2,1,COLS,1,col+1,1),puttext(80,1,80,1,blank_text)
#define insch(ch) movetext(col,1,COLS-1,1,col+1,1),putch(ch)
#define standout() textattr(0x7<<4)
#define standend() textattr(0x7)
#define beep() putchar('\007')
#define stdscr 0
static void hack_standout EXT4(int, int, int, int);
static char blank_text[] = { ' ', 0x07 };
static void printw();
#else
#undef USG
#undef NULL
#include <curses.h>
extern void tputs();
extern int wclear();
extern int wrefresh();
extern int endwin();
extern int wmove();
extern int wclrtoeol();
extern int printw();
extern int wdelch();
extern int waddch();
extern int winsch();
extern int waddstr();
#ifndef amiga
extern int wstandout();
extern int wstandend();
#endif
static void beep();
#endif
#include "sysdef.h"
#include "global.h"
#include "cell.h"
#include "kbd.h"
/* This must agree with io_term.c */
struct line {
int alloc;
char *buf;
};
/* Window flags:
0x01 Locked horizontally
0x02 Locked vertically
0x04 Page Horizontally
0x08 Page Vertically
0x10 Edges disabled
0x20 Edges standout
*/
#define WIN_LCK_HZ 0x01
#define WIN_LCK_VT 0x02
#define WIN_PAG_HZ 0x04
#define WIN_PAG_VT 0x08
#define WIN_EDGES 0x10
#define WIN_EDGE_REV 0x20
#define MIN_WIN_HEIGHT (cwin->win_flags&WIN_EDGES ? 2 : 1)
#define MIN_WIN_WIDTH (cwin->win_flags&WIN_EDGES ? 6 : 1)
struct window {
struct rng screen; /* Cells that are onscreen in this
window */
VOIDSTAR *win_slops; /* Slops in this window */
int win_over; /* Where the data in this window starts */
int win_down; /* on the screen. */
int win_flags; /* Various flags */
/* -1 if this window isn't linked to any others, else
contains the index into wins of the window this one is
linked to */
int win_linked;
/* Number of lines of spreadsheet that can fit in this window.
This only changes when the screen is resized,
win->flags&WIN_EDGES changes, or a window is either
created or destroyed */
int numr;
/* Number of text columns that can fit in this window.
This changes when the screen is resized,
win->flags&WIN_EDGES changes, a window is created or
destoryed, or win->lh_wid changes. In the last case
win->numc+win->lh_wid remains a constant. */
int numc;
/* Number of characters taken up by the row numbers at the
left hand edge of the screen. Zero if edges is
win->flags&WIN_EDGES is off (by definition). Seven (or
five) if win->flags&WIN_PAG_HZ (to make things easier).
Ranges between three "R9 " to seven "R32767 " depending on
the number of the highest row on the screen. */
int lh_wid;
/* Cursor row/column in this window */
/* Note that the external variables curow, cucol are used for
the currently active cursor position, so if you want
cwin->curow and cwin->cucol to be accurate, you have to
set them yourself. */
CELLREF curow,cucol;
};
#define LINE_MIN 28
/* in io_utils.c */
extern void flush_slops EXT1(VOIDSTAR);
extern int find_slop EXT5(VOIDSTAR, CELLREF, CELLREF, CELLREF *, CELLREF *);
extern void kill_slop EXT4(VOIDSTAR, CELLREF, CELLREF, CELLREF);
extern void change_slop EXT6(VOIDSTAR, CELLREF, CELLREF, CELLREF, CELLREF, CELLREF);
extern void set_slop EXT4(VOIDSTAR *, CELLREF, CELLREF, CELLREF);
extern char *print_cell EXT1(CELL *);
extern char *adjust_prc EXT5(char *, CELL *, int, int, int);
extern char *cell_value_string EXT2(CELLREF, CELLREF);
/* in io_term.c */
extern void set_line EXT2(struct line *,char *);
extern int get_chr EXT0();
extern int global_cmd EXT1(int);
extern struct keymap main_map;
extern struct keymap meta_map[];
extern int topclear;
extern CELLREF mkrow,mkcol;
extern CELLREF setrow,setcol;
extern unsigned int how_many;
extern const int rowmagic[],colmagic[];
#ifdef TEST
extern int dbg_do_stderr;
#endif
/* in regions.c */
extern void set_rng EXT5(struct rng *,CELLREF, CELLREF, CELLREF, CELLREF);
void cur_status EXT0();
void pr_cell EXT3(CELLREF, CELLREF, CELL *);
void set_numcols EXT2(struct window *, CELLREF);
void disp_scrn EXT0();
static void find_nonzero_width EXT1(struct window *);
static void hide_cell_cursor EXT0();
static void display_cell_cursor EXT0();
static void recenter_window EXT1(struct window *);
static void pr_cell_win EXT4(struct window *, CELLREF, CELLREF, CELL *);
/* Constants */
const char numb_oflo[] ="\
##############################################################################\
##############################################################################\
##############################################################################\
######";
static int nwin;
static struct window *wins;
static struct window *cwin;
int status = 2;
int input = 1;
int redrew = 0;
int textout = 0;
#define TOPLN 0x2
#undef CTRL
#define CTRL(X) ((X)&037)
#define META(X) ((X)|0200)
#define L_TOGGLE_OVER 0
#define L_BEG_LINE 1
#define L_END_LINE 2
#define L_BK_CHR 3
#define L_BK_WORD 4
#define L_BK_DEL_CHR 5
#define L_BK_DEL_WORD 6
#define L_BK_DEL_END 7
#define L_FW_CHR 8
#define L_FW_WORD 9
#define L_FW_DEL_CHR 10
#define L_FW_DEL_WORD 11
#define L_FW_DEL_END 12
#define L_FINISH 13
#define L_INS_EXPR 14
#define L_INS_VAL 15
#define L_INS_REL 16
#define L_INS_ABS 17
#define L_INS_CHR 18
struct cmd_func edit_funcs[] = {
{ "toggle-over-write", 0, TOPLN, 0 },
{ "cursor-begin-line", 0, TOPLN, 0 },
{ "cursor-end-line", 0, TOPLN, 0 },
{ "cursor-back-char", "n", TOPLN, 0 },
{ "cursor-back-word", "n", TOPLN, 0 },
{ "delete-prev-char", "n", TOPLN, 0 },
{ "delete-prev-word", "n", TOPLN, 0 },
{ "delete-to-start", 0, TOPLN, 0 },
{ "cursor-fwd-char", "n", TOPLN, 0 },
{ "cursor-fwd-word", "n", TOPLN, 0 },
{ "delete-next-char", "n", TOPLN, 0 },
{ "delete-next-word", "n", TOPLN, 0 },
{ "delete-to-end", 0, TOPLN, 0 },
{ "finish-line", 0, TOPLN, 0 },
{ "insert-cell-expression",0, TOPLN, 0 },
{ "insert-cell-value", 0, TOPLN, 0 },
{ "insert-rel-ref", 0, TOPLN, 0 },
{ "insert-abs-ref", 0, TOPLN, 0 },
{ "insert-character", "T", TOPLN, 0 },
{ 0, 0, 0, 0 }
};
static struct key edit_keys[] = {
{ 1, L_BEG_LINE }, /* ^A */
{ 1, L_BK_CHR },
{ 0, UNBOUND },
{ 1, L_FW_DEL_CHR },
{ 1, L_END_LINE }, /* ^E */
{ 1, L_FW_CHR },
{ 0, UNBOUND },
{ 1, L_BK_DEL_CHR },
{ 0, UNBOUND }, /* ^I */
{ 1, L_FINISH },
{ 1, L_FW_DEL_END },
{ 0, UNBOUND },
{ 1, L_FINISH }, /* ^M */
{ 0, UNBOUND },
{ 1, L_TOGGLE_OVER },
{ 0, UNBOUND },
{ 0, UNBOUND }, /* ^Q */
{ 0, UNBOUND },
{ 0, UNBOUND },
{ 0, UNBOUND },
{ 1, L_BK_DEL_END }, /* ^U */
{ 0, UNBOUND },
{ 0, UNBOUND },
{ 0, UNBOUND },
{ 0, UNBOUND },
{ 0, UNBOUND },
{ 255, 3 }
};
static struct key edit_1_keys[] = {
{ 1, L_INS_CHR }
};
static struct key edit_2_keys[] = {
{ 1, L_BK_DEL_CHR }
};
struct keymap edit_map[] = {
{
&edit_map[1], 0, 0, 1,
CTRL('A'), CTRL('['),
&edit_keys[0]
}, {
&edit_map[2], 0, 1, 1,
' ', '~',
&edit_1_keys[0]
},{
&main_map, 1, 0, 1,
'\177', '\177',
&edit_2_keys[0]
}
};
/* Beginning of the edit meta-keymap This is a sparse keymap */
static struct key emk3[] = {
{ 1, L_BK_DEL_WORD }
};
static struct key emk2[] = {
{ 1, L_INS_REL },
{ 0, UNBOUND },
{ 0, UNBOUND },
{ 0, UNBOUND },
{ 1, L_INS_VAL }
};
static struct key emk1[] = {
{ 1, L_INS_ABS },
{ 1, L_BK_WORD },
{ 0, UNBOUND },
{ 1, L_FW_DEL_WORD },
{ 1, L_INS_EXPR },
{ 1, L_FW_WORD },
};
struct keymap edit_meta_map[] = {
{
&edit_meta_map[1], 0, 0, 0,
CTRL('H'), CTRL('H'),
&emk3[0]
},{
&edit_meta_map[2], 0, 0, 0,
'A', 'F',
&emk1[0]
},{
&edit_meta_map[3], 0, 0, 0,
'R', 'V',
&emk2[0]
},{
&edit_meta_map[4], 0, 0, 0,
'a', 'f',
&emk1[0]
},{
&edit_meta_map[5], 0, 0, 0,
'r', 'v',
&emk2[0]
},{
&meta_map[0], 1, 0, 0,
'\177', '\177',
&emk3[0]
}
};
void
open_display FUN1(int,c)
{
extern unsigned short print_width;
initscr();
scrollok(stdscr,0);
#if !defined(__TURBOC__) && !defined(SYSV) && !defined(AMIGA)
if(c || !strncmp(getenv("TERM"),"xterm",5)) {
extern int stty EXT2(int, struct sgttyb *);
_tty.sg_ispeed=15;_tty.sg_ospeed=15;stty(_tty_ch,&_tty);
}
#endif
cbreak();
noecho();
nonl();
/* Must be after initscr() */
print_width=COLS;
nwin=1;
wins=cwin=ck_malloc(sizeof(struct window));
cwin->win_slops=(void *)0;
wins->win_over=0;
wins->win_down=3;
/* wins->win_edges=1; */
wins->win_flags= WIN_EDGES|WIN_EDGE_REV;
wins->win_linked= -1;
wins->numc=COLS;
wins->numr=LINES-3;
wins->lh_wid=0;
curow=wins->curow=MIN_ROW;
cucol=wins->cucol=MIN_COL;
}
void
close_display FUN0()
{
clear();
refresh();
(void)endwin();
}
void
clear_top_before FUN0()
{
textout=0;
if(topclear==2) {
move(input-1,0);
clrtoeol();
topclear=0;
}
move(0,0);
}
void
clear_top_after FUN0()
{
move(input-1,0);
clrtoeol();
topclear=0;
}
void
redisp FUN0()
{
refresh();
}
static int nline;
static int save_auto;
extern int auto_recalc;
void
text_start FUN0()
{
clear();
redisp();
nline=0;
save_auto=auto_recalc;
auto_recalc=0;
redrew++;
}
void
text_line FUN1N(char *,ptr)
{
va_list ap;
char sav;
char buf[1000];
var_start(ap,ptr);
vsprintf(buf,ptr,ap);
va_end(ap);
ptr=buf;
for(;;) {
if(nline==LINES-1) {
move(nline,0);
addstr("Press a key to to proceed: ");
refresh();
(void)get_chr();
clear();
nline=0;
}
move(nline++,0);
if(strlen(ptr)<=COLS) {
addstr(ptr);
break;
}
sav=ptr[COLS];
ptr[COLS]='\0';
addstr(ptr);
ptr[COLS]=sav;
refresh();
ptr+=COLS;
}
}
void
text_finish FUN0()
{
if(nline!=0) {
move(nline,0);
addstr("Press a key to continue: ");
refresh();
(void)get_chr();
}
auto_recalc=save_auto;
disp_scrn();
}
/* Return zero on success,
one on empty input,
and two on abort */
int
get_inp_line FUN2(char *,prompt, struct line *,line)
{
static int over; /* Overwrite or insert */
char *ptr; /* Current position in the line */
char *sptr; /* Start of the line */
char *eptr; /* End of the line */
int line_len; /* length of the line */
int col = 0; /* Current cursor column */
int plen; /* Length of the prompt */
int domove = 0;
int doscroll = 0;
int c;
int sfilled;
char *in_str;
int n;
int do_free;
char vbuf[50];
extern char *macro_func_arg;
extern struct cmd_func *cur_cmd;
extern int cur_chr;
extern unsigned char cur_vector;
#define BUFFER 10
#define MORE(bytes) \
line_len+=bytes; \
line->buf=ck_realloc(sptr,line_len+1); \
eptr= eptr-sptr + line->buf; \
ptr= ptr-sptr + line->buf; \
sptr= line->buf; \
#define KILLCH() \
{ \
if(ptr!=eptr) { \
char *tptr; \
for(tptr=ptr;tptr<=eptr;tptr++) \
tptr[-1]= tptr[0]; \
} \
--ptr; \
--eptr; \
--sfilled; \
--col; \
if(col<BUFFER) \
doscroll++; \
else if(!doscroll) { \
move(input-1,col); \
delch(); \
if(eptr-sptr+plen>=COLS && ptr+(COLS-1-col)<eptr) { \
mvaddch(input-1,COLS-1,ptr[COLS-1-col]);\
domove++; \
} \
} \
}
topclear=2;
if(macro_func_arg) {
set_line(line,macro_func_arg);
macro_func_arg=0;
return 0;
}
if(!line->alloc) {
line->alloc=LINE_MIN;
line->buf=ck_malloc(LINE_MIN);
line->buf[0]='\0';
}
line_len=line->alloc-1; /* Leave room for the NULL */
sptr=line->buf;
sfilled=strlen(sptr);
plen=strlen(prompt)+3;
ptr=sptr+sfilled;
eptr=ptr;
over=0;
doscroll++;
for(;;) {
if(domove) {
domove=0;
if(col<BUFFER || col>COLS-BUFFER)
doscroll++;
else
move(input-1,col);
}
if(doscroll) {
doscroll=0;
redrew=0;
if(textout==2) {
/* [MORE] the error msg, so the luser has
a chance to see it. . . */
mvaddstr(input-1,COLS-7,"[MORE]");
(void)get_chr();
}
textout=0;
move(input-1,0);
clrtoeol();
if(plen + (ptr-sptr)<COLS-BUFFER) {
*eptr=0;
printw("%s: %.*s",prompt,COLS-plen,sptr);
col=plen+(ptr-sptr);
} else {
char *p;
p=sptr+COLS-2*BUFFER-plen;
while(ptr-p>=COLS-BUFFER)
p+=COLS-2*BUFFER;
*eptr=0;
printw("%.*s",COLS,p);
col=ptr-p;
}
move(input-1,col);
}
if(how_many!=1) {
how_many=1;
cur_status();
move(input-1,col);
}
map_chr(EDIT_MAP);
swtch:
if(cur_vector!=1) {
n=global_cmd(EDIT_MAP);
if(redrew || textout)
doscroll++;
if(n==-3) {
*eptr++='\0';
return 2;
} else if(n==-2) {
beep();
beep();
} else if(n>=0)
goto swtch;
continue;
}
switch(cur_cmd-edit_funcs) {
case L_BEG_LINE:
col-=ptr-sptr;
ptr=sptr;
domove++;
break;
case L_BK_CHR:
for(n=0;ptr!=sptr && n<how_many;n++) {
--ptr;
--col;
}
domove++;
break;
case L_BK_WORD:
for(n=0;ptr!=sptr && n<how_many;n++) {
while(ptr!=sptr && !isalnum(ptr[-1])) {
--ptr;
--col;
}
while(ptr!=sptr && isalnum(ptr[-1])) {
--ptr;
--col;
}
}
domove++;
break;
case L_FW_DEL_CHR:
for(n=0;ptr!=eptr && n<how_many;n++) {
ptr++;
col++;
KILLCH()
}
break;
case L_FW_DEL_WORD:
for(n=0;ptr!=eptr && n<how_many;n++) {
while(ptr!=eptr && !isalnum(ptr[0])) {
ptr++;
col++;
KILLCH()
}
while(ptr!=eptr && isalnum(ptr[0])) {
ptr++;
col++;
KILLCH()
}
}
break;
case L_END_LINE:
col+=eptr-ptr;
ptr=eptr;
domove++;
break;
case L_FW_CHR:
for(n=0;ptr!=eptr && n<how_many;n++) {
col++;
ptr++;
}
domove++;
break;
case L_FW_WORD:
for(n=0;ptr!=eptr && n<how_many;n++) {
while(ptr!=eptr && !isalnum(ptr[0])) {
col++;
ptr++;
}
while(ptr!=eptr && isalnum(ptr[0])) {
col++;
ptr++;
}
}
domove++;
break;
case L_FW_DEL_END:
eptr=ptr;
clrtoeol();
break;
case L_TOGGLE_OVER:
over= !over;
break;
case L_BK_DEL_WORD:
for(n=0;ptr!=sptr && n<how_many;n++) {
while(ptr!=sptr && !isalnum(ptr[-1]))
KILLCH()
while(ptr!=sptr && isalnum(ptr[-1]))
KILLCH()
}
break;
case L_BK_DEL_END:
while(ptr!=sptr)
KILLCH()
break;
case L_BK_DEL_CHR:
for(n=0;ptr!=sptr && n<how_many;n++)
KILLCH()
break;
case L_FINISH:
*eptr++='\0';
textout=1;
return eptr-sptr==1 ? 1 : 0;
case L_INS_EXPR:
{
CELL *cp;
if(!(cp=find_cell(curow,cucol)))
break;
in_str=decomp(curow,cucol,cp);
do_free=1;
}
goto insert_string;
case L_INS_VAL:
in_str=cell_value_string(curow,cucol);
do_free=0;
goto insert_string;
case L_INS_REL:
#ifdef A0_REFS
if(mkrow!=NON_ROW) {
struct rng r;
set_rng(&r,curow,cucol,mkrow,mkcol);
in_str=range_name(&r);
} else
in_str=cell_name(curow,cucol);
#else
if(mkrow!=NON_ROW) {
switch( ((curow==setrow)<<3)
+ ((mkrow==setrow)<<2)
+ ((cucol==setcol)<<1)
+ (mkcol==setcol)) {
case 0:
case 1:
case 2:
case 4:
case 5:
case 6:
case 8:
case 9:
case 10:
sprintf(vbuf,"r[%+d:%+d]c[%+d:%+d]",
(curow < mkrow ? curow : mkrow) - setrow,
(curow < mkrow ? mkrow : curow) - setrow,
(cucol < mkcol ? cucol : mkcol) - setcol,
(cucol < mkcol ? mkcol : cucol) - setcol);
break;
case 3:
case 7:
case 11:
sprintf(vbuf,"r[%+d:%+d]c",
(curow < mkrow ? curow : mkrow) - setrow,
(curow < mkrow ? mkrow : curow) - setrow);
break;
case 12:
case 14:
case 13:
sprintf(vbuf,"rc[%+d:%+d]",
(cucol < mkcol ? cucol : mkcol) - setcol,
(cucol < mkcol ? mkcol : cucol) - setcol);
break;
case 15:
strcpy(vbuf,"rc");
break;
#ifdef TEST
default:
panic("Unknown value");
#endif
}
} else {
switch(((curow==setrow)<<1) + (cucol==setcol)) {
case 0:
sprintf(vbuf,"r[%+d]c[%+d]",curow-setrow,cucol-setcol);
break;
case 1:
sprintf(vbuf,"r[%+d]c",curow-setrow);
break;
case 2:
sprintf(vbuf,"rc[%+d]",cucol-setcol);
break;
case 3:
strcpy(vbuf,"rc");
break;
#ifdef TEST
default:
panic("huh what");
#endif
}
}
in_str=vbuf;
#endif
do_free=0;
goto insert_string;
case L_INS_ABS:
/* Insert current cell/range name as an absolute reference */
#ifdef A0_REFS
if(mkrow!=NON_ROW)
sprintf(vbuf,"$%s$%u:$%s:$%u",col_to_str(cucol),curow,col_to_str(mkcol),mkrow);
else
sprintf(vbuf,"$%s$%u",col_to_str(cucol), curow);
in_str=vbuf;
#else
if(mkrow!=NON_ROW) {
struct rng r;
set_rng(&r,curow,cucol,mkrow,mkcol);
in_str=range_name(&r);
} else
in_str=cell_name(curow,cucol);
#endif
do_free=0;
insert_string:
c=strlen(in_str);
if((sfilled + (over ? c + (ptr-eptr) : c)) >= line_len) {
n= over ? c + (ptr-eptr) : c;
if(n<LINE_MIN)
n=LINE_MIN;
MORE(n);
}
if(over) {
if(ptr+c>eptr) {
sfilled+=(ptr+c)-eptr;
eptr=ptr+c;
}
} else {
if(ptr!=eptr) {
char *tptr;
for(tptr=eptr;tptr>=ptr;--tptr)
tptr[c]=tptr[0];
}
eptr+=c;
sfilled+=c;
}
bcopy(in_str,ptr,c);
ptr+=c;
if(col+c>=COLS-BUFFER) {
doscroll++;
} else {
col+=c;
if(!over && ptr!=eptr) {
#ifdef __TURBOC__
movetext(col-c,1,COLS-c,1,col,1);
#else
while(c--)
insch(' ');
#endif
}
addstr(in_str);
}
if(do_free)
decomp_free();
break;
case L_INS_CHR:
if((sfilled+how_many + (over ? (ptr-eptr) : (0))) >= line_len) {
n = over ? how_many+(ptr-eptr) : how_many;
if(n<LINE_MIN)
n=LINE_MIN;
MORE(n);
}
if(over) {
if(ptr+how_many>eptr) {
sfilled+=(ptr+how_many)-eptr;
eptr=ptr+how_many;
}
} else {
if(ptr!=eptr) {
char *tptr;
for(tptr=eptr;tptr>=ptr;--tptr)
tptr[how_many]=tptr[0];
}
eptr+=how_many;
sfilled+=how_many;
}
for(n=0;n<how_many;n++)
*ptr++=cur_chr;
if(col+how_many>=COLS-BUFFER) {
doscroll++;
} else if(over || ptr==eptr) {
col+=how_many;
for(n=0;n<how_many;n++)
addch(cur_chr);
} else {
col+=how_many;
for(n=0;n<how_many;n++) {
insch(cur_chr);
move(input-1,col);
}
}
break;
}
}
#undef KILLCH
#undef BUFFER
#undef MORE
}
/* External interface to window routines */
/* Create a new window by splitting the current one. */
void
open_window FUN1(char *,text)
{
int hv;
int where;
int tmp;
struct window *win;
while(*text==' ')
text++;
if(*text=='h' || *text=='H') {
hv=1;
} else if(*text=='v' || *text=='V') {
hv=0;
} else {
error_msg("Open 'h'orizontal or 'v'ertical window, not '%s'",text);
return;
}
where=atoi(text+1);
if( (!hv && ( where<MIN_WIN_WIDTH
|| cwin->numc-where<MIN_WIN_WIDTH))
|| ( hv && ( where<MIN_WIN_HEIGHT
|| cwin->numr-where<MIN_WIN_HEIGHT))) {
error_msg("Window won't fit!");
return;
}
nwin++;
tmp=cwin-wins;
wins=ck_realloc(wins,nwin*sizeof(struct window));
win= &wins[nwin-1];
win->win_slops=(void *)0;
cwin= &wins[tmp];
win->win_over=cwin->win_over + (hv ? 0 : where) - cwin->lh_wid;
win->win_down=cwin->win_down + (hv ? where : 0);
win->win_flags = cwin->win_flags;
win->win_linked= -1;
win->lh_wid=0;
win->numc=cwin->numc + cwin->lh_wid + (hv ? 0 : -where);
win->numr=cwin->numr + (hv ? -where : 0);
win->curow=curow;
win->cucol=cucol;
set_numcols(win,curow);
cwin->numc-=(hv ? 0 : win->numc+win->lh_wid);
cwin->numr-=(hv ? (win->numr+(win->lh_wid?1:0)) : 0);
cwin->curow=curow;
cwin->cucol=cucol;
hide_cell_cursor();
win=cwin;
cwin= &wins[nwin-1];
recenter_window(cwin);
recenter_window(win);
disp_scrn();
}
static void do_close_window FUN1(int, num)
{
int n;
struct window *win,*kwin;
int nlf,nrt,nup,nbl;
int klo,kho,kld,khd;
int lo,ho,ld,hd;
struct tmp {
int l,
r,
u,
b;
} *tmpptr;
void recenter_all_win EXT0();
tmpptr=ck_malloc(sizeof(struct tmp)*nwin);
kwin= &wins[num];
nlf=nrt=nup=nbl=0;
klo=kwin->win_over-kwin->lh_wid;
kho=kwin->win_over+kwin->numc-1;
kld=kwin->win_down-(kwin->lh_wid?1:0);
khd=kwin->win_down+kwin->numr-1;
for(win=wins;win<&wins[nwin];win++) {
lo=win->win_over-win->lh_wid;
ho=win->win_over+win->numc-1;
ld=win->win_down-(win->lh_wid?1:0);
hd=win->win_down+win->numr-1;
/* Match to the left ? */
if(lo==kho+1) {
if(ld>=kld && hd<=khd)
tmpptr[nrt++].r=win-wins;
else if(hd>=kld && ld<=khd)
nrt= nwin;
}
else if(ho==klo-1) {
if(ld>=kld && hd<=khd)
tmpptr[nlf++].l=win-wins;
else if(hd>=kld && ld<=khd)
nlf= nwin;
}
else if(ld==khd+1) {
if(lo>=klo && ho<=kho)
tmpptr[nbl++].b=win-wins;
else if(ho>=kho && lo<=kho)
nbl= nwin;
}
else if(hd==kld-1) {
if(lo>=klo && ho<=kho)
tmpptr[nup++].u=win-wins;
else if(ho>=kho && lo<=kho)
nup= nwin;
}
}
if(nrt==0)
nrt=nwin;
if(nlf==0)
nlf=nwin;
if(nbl==0)
nbl=nwin;
if(nup==0)
nup=nwin;
if(nrt<=nlf && nrt<=nbl && nrt<=nup) {
for(n=0;n<nrt;n++) {
wins[tmpptr[n].r].numc+=kwin->lh_wid+kwin->numc;
wins[tmpptr[n].r].win_over-=kwin->lh_wid+kwin->numc;
}
} else if(nlf<=nbl && nlf<=nup) {
for(n=0;n<nlf;n++)
wins[tmpptr[n].l].numc+=kwin->lh_wid+kwin->numc;
} else if(nbl<=nup) {
for(n=0;n<nbl;n++) {
wins[tmpptr[n].b].numr+=kwin->numr+(kwin->lh_wid ? 1 : 0);
wins[tmpptr[n].b].win_down-=kwin->numr+(kwin->lh_wid ? 1 : 0);
}
} else {
for(n=0;n<nup;n++)
wins[tmpptr[n].u].numr+=kwin->numr+(kwin->lh_wid ? 1 : 0);
}
if(kwin==cwin && kwin!= wins)
--cwin;
if(cwin==&wins[nwin-1])
--cwin;
while(kwin< &wins[nwin]) {
*kwin= kwin[1];
kwin++;
}
--nwin;
recenter_all_win();
return;
}
void
close_window FUN1(char *,text)
{
int num;
num=atoi(text)-1;
if(num<0 || num>=nwin) {
error_msg("Window %s?",text);
return;
}
if(nwin==1) {
error_msg("You can't close the last window!");
return;
}
do_close_window(num);
}
void
goto_window FUN1(char *,text)
{
int n;
n=atoi(text)-1;
if(n<0 || n>nwin) {
error_msg("Window %s doesn't exist.",text);
return;
}
hide_cell_cursor();
cwin->curow=curow;
cwin->cucol=cucol;
cwin= &wins[n];
curow=cwin->curow;
cucol=cwin->cucol;
display_cell_cursor();
}
static int locmp FUN2(struct window **,a, struct window **,b)
{
return (*a)->win_down-(*b)->win_down;
}
static int hicmp FUN2(struct window **,a, struct window **,b)
{
return ((*a)->win_down+(*a)->numr)-((*b)->win_down+(*b)->numr);
}
/* How this works: First figure out how many lines are now avaliable for
sheet data. Then squeeze/stretch the windows to fit that space. . . */
static void resize_screen FUN0()
{
int n;
int nlines;
int firstln;
/* int shifted; */
int lo,sq,hi;
struct window **t;
if(input<LINES/2) {
if(status>LINES/2) {
nlines=status-input-1;
firstln=input+1;
} else {
firstln=1+input>status?input:status;
nlines=LINES-firstln;
}
} else if(status<LINES/2) {
nlines=input-status;
firstln=status+1;
} else {
firstln=1;
nlines=(input>status?status:input)-1;
}
t=ck_malloc(nwin*sizeof(struct window *));
for(n=0;n<nwin;n++)
t[n]= &wins[n];
qsort(t,nwin,sizeof(struct window *),hicmp);
hi=t[0]->win_down+t[0]->numr;
sq=firstln+nlines-hi;
for(n=0;n<nwin && hi==t[n]->win_down+t[0]->numr;n++) {
t[n]->numr-=sq;
}
qsort(t,nwin,sizeof(struct window *),locmp);
lo=t[0]->win_down;
sq=firstln-lo+((t[0]->win_flags&WIN_EDGES)?1:0);
for(n=0;n<nwin && t[n]->win_down==lo;n++) {
t[n]->numr-=sq;
t[n]->win_down=firstln+((t[0]->win_flags&WIN_EDGES)?1:0);
}
cwin->curow=curow;
cwin->cucol=cucol;
for(n=0;n<nwin;n++) {
if(wins[n].numr<=0) {
do_close_window(n);
n--;
} else
recenter_window(&wins[n]);
}
disp_scrn();
}
#if 0
static void shift_screen FUN1(int, by)
{
int n;
for(n=0;n<nwin;n++)
wins[n].win_down+=by;
disp_scrn();
}
#endif
int
set_window_option FUN2(int,set_opt, char *,text)
{
int n;
static struct opt {
char *text;
int bits;
} opts[] = {
{ "reverse", WIN_EDGE_REV },
{ "standout", WIN_EDGE_REV },
{ "page", WIN_PAG_HZ|WIN_PAG_VT },
{ "pageh", WIN_PAG_HZ },
{ "pagev", WIN_PAG_VT },
{ "lockh", WIN_LCK_HZ },
{ "lockv", WIN_LCK_VT }
};
if(set_opt && !strincmp(text,"status ",7)) {
n=atoi(text+7);
if(n>LINES || n<-LINES) {
error_msg("%s?",text);
return 1;
}
if(n<0)
n=LINES+1+n;
status=n;
resize_screen();
} else if(set_opt && !strincmp(text,"input ",6)) {
n=atoi(text+6);
if(n==0 || n>LINES || n<-LINES) {
error_msg("%s?",text);
return 1;
}
if(n<0)
n=LINES+1+n;
input=n;
resize_screen();
} else if(!strincmp(text,"link",4)) {
if(set_opt) {
n=atoi(text+4)-1;
if(n<0 || n>nwin)
error_msg("Can't '%s': window # out of range",text);
else
cwin->win_linked= n;
} else
cwin->win_linked= -1;
} else if(set_opt && !stricmp(text,"unlink")) {
cwin->win_linked= -1;
} else if(!stricmp(text,"edges")) {
if(set_opt) {
if((cwin->win_flags&WIN_EDGES)==0) {
if(cwin->numr<2 || cwin->numc<6)
error_msg("Edges wouldn't fit!");
cwin->win_flags|= WIN_EDGES;
cwin->win_down++;
cwin->numr--;
/* set_numcols(cwin,cwin->screen.hr); */
}
} else {
if(cwin->win_flags&WIN_EDGES) {
cwin->win_flags&= ~WIN_EDGES;
cwin->win_over-=cwin->lh_wid;
cwin->numc+=cwin->lh_wid;
cwin->lh_wid=0;
cwin->win_down--;
cwin->numr++;
}
}
} else if(set_opt && !strincmp(text,"row ",4)) {
text+=4;
curow=astol(&text);
} else if(set_opt && !strincmp(text,"col ",4)) {
text+=4;
cucol=astol(&text);
} else {
for(n=0;n<sizeof(opts)/sizeof(struct opt);n++) {
if(!stricmp(text,opts[n].text)) {
if(set_opt)
cwin->win_flags|= opts[n].bits;
else
cwin->win_flags&= ~opts[n].bits;
break;
}
}
if(n==sizeof(opts)/sizeof(struct opt))
return 0;
}
return 1;
}
void
show_window_options FUN0()
{
int n;
struct window *win;
cwin->curow=curow;
cwin->cucol=cucol;
win= &wins[0];
if(status)
text_line("Status line at %d", status);
else
text_line("Status line disabled.");
text_line("");
for(n=0;n<nwin;n++) {
text_line("Window #%d showing %s, with cursor at %s",
n+1,
range_name(&(win->screen)),
cell_name(win->curow,win->cucol));
text_line(" Options: %sedges (%sreverse)%s%s%s%s",
win->win_flags&WIN_EDGES ? "" : "no",
win->win_flags&WIN_EDGE_REV ? "" : "no",
win->win_flags&WIN_PAG_HZ ? ", pageh" : "",
win->win_flags&WIN_PAG_VT ? ", pagev" : "",
win->win_flags&WIN_LCK_HZ ? ", lockh" : "",
win->win_flags&WIN_LCK_VT ? ", lockv" : "");
if(win->win_linked!=-1)
text_line("Linked to window %d",win->win_linked+1);
win++;
}
}
#ifdef TEST
void
dbg_show_wins FUN0()
{
int n;
for(n=0;n<nwin;n++) {
text_line("Window %d",n);
text_line(" screen %s slops %p flags %x linked %d",
range_name(&(wins[n].screen)),wins[n].win_slops,wins[n].win_flags,
wins[n].win_linked);
text_line(" ov %d dn %d nr %d nc %d lh_wid %d pos %s",wins[n].win_over,wins[n].win_down,wins[n].numr,wins[n].numc,wins[n].lh_wid,cell_name(wins[n].curow,wins[n].cucol));
text_line("");
}
}
#endif
void
disp_scrn FUN0()
{
CELLREF cc,rr;
int n,n1;
CELL *cp;
struct window *win;
clear();
redrew++;
for(win=wins;win<&wins[nwin];win++) {
if(win->lh_wid) {
move(win->win_down-1,win->win_over-win->lh_wid);
printw("#%*d ", win->lh_wid-2, 1+win-wins);
if(win->win_flags&WIN_EDGE_REV)
standout();
cc=win->screen.lc;
do {
n=get_width(cc);
if(n>win->numc)
n=win->numc;
if(n>1) {
char *ptr;
#ifdef A0_REFS
ptr=col_to_str(cc);
#else
char buf[30];
sprintf(buf,"C%u",cc);
ptr=buf;
#endif
--n;
n1=strlen(ptr);
if(n<n1)
printw("%.*s ",n,"###############");
else {
n1=(n-n1)/2;
printw("%*s%-*s ",n1,"",n-n1,ptr);
}
} else if(n==1)
addstr("#");
} while(cc++<win->screen.hc);
rr=win->screen.lr;
do {
move(rr+win->win_down-win->screen.lr,win->win_over-win->lh_wid);
#ifdef A0_REFS
printw("%-*d ",win->lh_wid-1,rr);
#else
printw("R%-*d",win->lh_wid-1,rr);
#endif
} while(rr++<win->screen.hr);
if(win->win_flags&WIN_EDGE_REV)
standend();
}
flush_slops(win->win_slops);
find_cells_in_range(&(win->screen));
while(cp=next_row_col_in_range(&rr,&cc))
if(GET_TYP(cp))
{
pr_cell_win(win,rr,cc,cp);
}
}
if(!(cp=find_cell(curow,cucol)) || !GET_TYP(cp))
display_cell_cursor();
cur_status();
}
void
set_numcols FUN2(struct window *,win, CELLREF,hr)
{
int lh;
if((win->win_flags&WIN_EDGES)==0)
lh=0;
#if BITS_PER_CELLREF>8
else if((win->win_flags&WIN_PAG_HZ) || hr>=10000)
lh=7;
else if(hr>=1000)
lh=6;
else if(hr>=100)
lh=5;
#else
else if((win->win_flags&WIN_PAG_HZ) || hr>=100)
lh=5;
#endif
else if(hr>10)
lh=4;
else
lh=3;
win->win_over-=win->lh_wid-lh;
win->numc+=win->lh_wid-lh;
win->lh_wid=lh;
}
static void
move_cursor_to FUN3(struct window *,win, CELLREF, r,CELLREF, c)
{
int cc;
int cursor_col;
cursor_col=win->win_over;
for(cc=win->screen.lc;cc<c;cc++)
cursor_col+=get_width(cc);
move(win->win_down+r-win->screen.lr,cursor_col);
}
void
pr_cell FUN3(CELLREF, r, CELLREF, c, CELL *, cp)
{
int xx,yy;
struct window *win = (void *)0;
getyx(stdscr,yy,xx);
for(win=wins;win<&wins[nwin];win++) {
if( r<win->screen.lr || r>win->screen.hr
|| c<win->screen.lc || c>win->screen.hc)
continue;
pr_cell_win(win,r,c,cp);
}
move(yy,xx);
}
static void
pr_cell_win FUN4(struct window *,win, CELLREF, r, CELLREF, c, CELL *, cp)
{
int glowing;
int lenstr;
int j;
int wid,wwid;
char *ptr;
wid=get_width(c);
if(!wid)
return;
if(wid>win->numc)
wid=win->numc;
glowing = (r==curow && c==cucol && win==cwin);
ptr=print_cell(cp);
#ifdef TEST
if(!ptr)
panic("print_cell returned 0");
#endif
move_cursor_to(win,r,c);
if(glowing)
standout();
j=GET_JST(cp);
if(j==JST_DEF)
j=default_jst;
lenstr=strlen(ptr);
if(lenstr<=wid-1) {
CELLREF ccl,cch;
if(j==JST_LFT)
printw("%-*.*s",wid, wid-1,ptr);
else if(j==JST_RGT)
printw("%*.*s ",wid-1, wid-1,ptr);
else if(j==JST_CNT) {
wid=(wid-1)-lenstr;
printw("%*s%*s ",(wid+1)/2+lenstr,ptr,wid/2,"");
}
#ifdef TEST
else
panic("Unknown justification");
#endif
if(glowing)
standend();
if(lenstr==0 && c>win->screen.lc && find_slop(win->win_slops,r,c-1,&ccl,&cch)) {
CELLREF ccdl,ccdh;
if(find_slop(win->win_slops, r,c,&ccdl,&ccdh) && ccdl==c) {
kill_slop(win->win_slops, r,ccdl,ccdh);
for(;ccdh!=ccdl;--ccdh)
if(ccdh!=c && (wid=get_width(ccdh))) {
move_cursor_to(win,r,ccdh);
printw("%*s",wid,"");
}
}
kill_slop(win->win_slops, r,ccl,cch);
pr_cell(r,ccl,find_cell(r,ccl));
} else if(find_slop(win->win_slops, r,c,&ccl,&cch)) {
kill_slop(win->win_slops, r,ccl,cch);
for(;cch!=ccl;--cch)
if(cch!=c && (wid=get_width(cch))) {
move_cursor_to(win,r,cch);
printw("%*s",wid,"");
}
pr_cell(r,ccl,find_cell(r,ccl));
}
} else {
CELLREF cc=c;
CELL *ccp;
CELLREF ccl,cch;
for(wwid=wid;lenstr>wwid-1;wwid+=get_width(cc)) {
if( ++cc>win->screen.hc
|| ( ccp=find_cell(r,cc))
&& GET_TYP(ccp)
&& ( GET_FMT(ccp)!=FMT_HID
|| ( GET_FMT(ccp)==FMT_DEF
&& default_fmt!=FMT_HID))) {
--cc;
break;
}
}
if(lenstr>wwid-1)
if(GET_TYP(cp)==TYP_FLT)
ptr=adjust_prc(ptr,cp,wwid-1,wid-1,j);
else if(GET_TYP(cp)==TYP_INT)
ptr=(char *)numb_oflo;
if(wwid==1) {
addch(' ');
if(glowing)
standend();
} else if(wwid==wid) {
printw("%-*.*s ",wwid-1,wwid-1,ptr);
if(glowing)
standend();
} else if(glowing) {
printw("%.*s",wid,ptr);
standend();
printw("%-*.*s ",wwid-wid-1,wwid-wid-1,ptr+wid);
} else if(r==curow && (cucol>c && cucol<=cc)) {
CELLREF ctmp;
int w_left;
int w_here;
w_left=wid;
for(ctmp=c+1;ctmp<cucol;ctmp++)
w_left+=get_width(ctmp);
printw("%.*s",w_left,ptr);
standout();
w_here=get_width(cucol);
if(wwid>w_left+w_here) {
printw("%-*.*s",w_here,w_here,ptr+w_left);
standend();
printw("%-*.*s ",wwid-(w_left+w_here)-1,wwid-(w_left+w_here)-1,ptr+w_left+w_here);
} else {
printw("%-*.*s",w_here,w_here-1,ptr+w_left);
standend();
}
} else
printw("%-*.*s ",wwid-1,wwid-1,ptr);
if(find_slop(win->win_slops, r,c,&ccl,&cch)) {
change_slop(win->win_slops, r,ccl,cch,c,cc);
for(;cch>cc;--cch)
if(wid=get_width(cch)) {
move_cursor_to(win,r,cch);
printw("%*s",wid,"");
}
for(cch=c-1;cch>ccl;--cch)
if(wid=get_width(cch)) {
move_cursor_to(win,r,cch);
printw("%*s",wid,"");
}
if(ccl!=c)
pr_cell(r,ccl,find_cell(r,ccl));
} else
set_slop((VOIDSTAR *)(&(win->win_slops)), r,c,cc);
}
if(glowing)
cur_status();
}
void
cur_status FUN0()
{
CELL *cp;
char *dec;
char *ptr;
static char hmbuf[40];
int wid;
int plen;
int dlen;
int yy,xx;
if(!status)
return;
getyx(stdscr,yy,xx);
move(status-1,0);
wid=COLS-2;
if(mkrow!=NON_ROW) {
struct rng r;
addch('*');
--wid;
set_rng(&r,curow,cucol,mkrow,mkcol);
ptr=range_name(&r);
} else
ptr=cell_name(curow,cucol);
addstr(ptr);
wid-=strlen(ptr);
if(how_many!=1) {
sprintf(hmbuf," {%u}",how_many);
addstr(hmbuf);
wid-=strlen(hmbuf);
}
if((cp=find_cell(curow,cucol)) && cp->cell_formula) {
dec=decomp(curow,cucol,cp);
dlen=strlen(dec);
} else {
dec=0;
dlen=0;
}
ptr=cell_value_string(curow,cucol);
plen=strlen(ptr);
if(dec) {
wid-=4;
if(dlen+plen>wid) {
if(plen+3>wid)
printw(" %.*s... [...]",wid-6,ptr);
else
printw(" %s [%.*s...]",ptr,wid-plen-3,dec);
} else
printw(" %s [%s]",ptr,dec);
decomp_free();
} else if(plen) {
--wid;
if(plen>wid)
printw(" %.*s...",wid-3,ptr);
else
printw(" %s",ptr);
}
clrtoeol();
move(yy,xx);
}
static void
display_cell_cursor FUN0()
{
int cc;
int cursor_row;
int cursor_col;
int cwid;
#ifndef __TURBOC__
int n;
#endif
cursor_col=cwin->win_over;
for(cc=cwin->screen.lc;cc<cucol;cc++)
{
cursor_col+=get_width(cc);
}
cursor_row=cwin->win_down+curow-cwin->screen.lr;
cwid=get_width(cucol);
if(cwid>cwin->numc)
cwid=cwin->numc;
#ifdef __TURBOC__
hack_standout(1,cursor_row,cursor_col,cwid);
#else
move(cursor_row,cursor_col);
standout();
for(n=cwid;n;n--)
#ifdef A_STANDOUT
addch(inch()|A_STANDOUT);
#else
addch(inch());
#endif
standend();
#endif
}
static void
hide_cell_cursor FUN0()
{
int cc;
int cursor_row;
int cursor_col;
int cwid;
#ifndef __TURBOC__
int n;
#endif
cursor_col=cwin->win_over;
for(cc=cwin->screen.lc;cc<cucol;cc++)
{
cursor_col+=get_width(cc);
}
cursor_row=cwin->win_down+curow-cwin->screen.lr;
cwid=get_width(cucol);
if(cwid>cwin->numc)
cwid=cwin->numc;
#ifdef __TURBOC__
hack_standout(0,cursor_row,cursor_col,cwid);
#else
move(cursor_row,cursor_col);
for(n=cwid;n;n--)
#ifdef SYSV
addch(inch()&~A_STANDOUT);
#else
addch(inch());
#endif
#endif
}
#ifdef __TURBOC__
static void
hack_standout FUN4(int,standp, int,rown, int,coln, int,cols)
{
char buf[COLS*2];
char *ptr;
int n;
standp = standp ? 0x7<<4 : 0x7;
rown++;
coln++;
gettext(coln,rown,coln+cols-1,rown,buf);
ptr=buf+1;
n=cols;
while(n--) {
*ptr= standp;
ptr+=2;
}
puttext(coln,rown,coln+cols-1,rown,buf);
}
static void
printw FUN1N(char *,str)
{
va_list ap;
char text[COLS+1];
var_start(ap,str);
vsprintf(text,str,ap);
addstr(text);
va_end(ap);
}
#endif
int
get_chr_prompt FUN1(char *,prompt)
{
mvaddstr(input-1,0,prompt);
clrtoeol();
topclear=2;
refresh();
return get_chr();
}
void
error_msg FUN1N(char *,str)
{
va_list foo;
char buf[1000];
/* Sigh. What I'd give for vprintw() */
#ifdef TEST
extern int isatty();
if(!dbg_do_stderr)
dbg_do_stderr= isatty(fileno(stderr)) ? 1 : 2;
#endif
var_start(foo,str);
vsprintf(buf,str,foo);
#ifdef TEST
if(dbg_do_stderr==2) {
fputs(buf,stderr);
putc('\n',stderr);
fflush(stderr);
}
#endif
if(textout==2) {
mvaddstr(input-1,COLS-7,"[MORE]");
(void)get_chr();
} else
textout=2;
mvaddstr(input-1,0,buf);
clrtoeol();
topclear=1;
refresh();
}
void
info_msg FUN1N(char *,str)
{
va_list foo;
char buf[1000];
/* See previous comment */
var_start(foo,str);
vsprintf(buf,str,foo);
if(!status) {
if(textout==2) {
mvaddstr(input-1,COLS-7,"[MORE]");
(void)get_chr();
}
textout=1;
mvaddstr(input-1,0,buf);
} else
mvaddstr(status-1,0,buf);
clrtoeol();
refresh();
}
#ifndef amiga
void
_putchar FUN1(int, ch)
{
(void)putc(ch,stdout);
/* (void)putchar(ch); */
}
#endif
#ifndef __TURBOC__
static void
beep FUN0()
{
#ifdef SYSV
_putchar('\007');
#else
static char *vb;
static called;
if(!called) {
called++;
vb=getcap("vb");
}
if(vb) {
_puts(vb);
} else {
_putchar('\007');
}
#endif
}
#endif
void
shift_linked_window FUN2(long,dn, long,ov)
{
struct window *win;
win=cwin;
while(win->win_linked!=-1) {
win= &wins[win->win_linked];
if(win==cwin) /* Loop check! */
return;
if((win->win_flags&WIN_LCK_VT)==0)
win->curow+=dn;
if((win->win_flags&WIN_LCK_HZ)==0)
win->cucol+=ov;
if( win->curow<win->screen.lr || win->curow>win->screen.hr
|| win->cucol<win->screen.lc || win->cucol>win->screen.hc)
recenter_window(win);
}
}
int
move_cell_cursor FUN2(CELLREF,rr, CELLREF,cc)
{
int ret;
int cx,cy;
if(cwin->win_linked!=-1)
shift_linked_window((long)rr-curow,(long)cc-cucol);
if( rr<cwin->screen.lr || rr>cwin->screen.hr
|| cc<cwin->screen.lc || cc>cwin->screen.hc) {
cwin->curow=curow=rr;
cwin->cucol=cucol=cc;
recenter_window(cwin);
disp_scrn();
ret=1;
} else {
getyx(stdscr,cy,cx);
hide_cell_cursor();
curow=rr;
cucol=cc;
display_cell_cursor();
cur_status();
move(cy,cx);
ret=0;
}
if(get_width(cucol)==0)
find_nonzero_width(cwin);
return ret;
}
static void
find_nonzero_width FUN1(struct window *,win)
{
CELLREF cc;
unsigned short n;
cc=cucol;
if(cc<win->screen.hc) {
cc++;
while((n=get_width(cc))==0) {
if(cc==win->screen.hc)
break;
cc++;
}
if(n) {
cucol=cc;
return;
}
}
if(cc>win->screen.lc) {
--cc;
while((n=get_width(cc))==0) {
if(cc==win->screen.lc)
break;
--cc;
}
if(n) {
cucol=cc;
return;
}
}
}
void
recenter_all_win FUN0()
{
int n;
cwin->curow=curow;
cwin->cucol=cucol;
for(n=0;n<nwin;n++)
recenter_window(&wins[n]);
disp_scrn();
}
void
recenter_cur_win FUN0()
{
cwin->curow=curow;
cwin->cucol=cucol;
recenter_window(cwin);
disp_scrn();
}
static void
recenter_window FUN1(struct window *,win)
{
CELLREF lr,hr,lc,hc;
CELLREF rr;
unsigned short w,ww;
unsigned short n;
unsigned short totwid = 0;
int more;
if(get_width(win->cucol)==0)
find_nonzero_width(win);
if(win->win_flags&WIN_PAG_VT) {
lr=MIN_ROW+win->numr * ((win->curow-MIN_ROW)/win->numr);
hr = (lr>MAX_ROW-win->numr) ? MAX_ROW : lr+win->numr-1;
} else {
rr=win->numr/2;
lr= (win->curow<=rr) ? MIN_ROW : (win->curow-rr);
if(lr>=MAX_ROW-win->numr) {
hr=MAX_ROW;
lr=hr+1-win->numr;
} else
hr=lr+win->numr-1;
}
set_numcols(win,hr);
if(win->win_flags&WIN_PAG_HZ) {
lc=hc=MIN_COL;
w=get_width(hc);
for(;;) {
ww=get_width(hc+1);
while(w+ww<=win->numc && hc<MAX_COL) {
hc++;
w+=ww;
ww=get_width(hc+1);
}
if(hc>=win->cucol)
break;
hc++;
lc=hc;
w=ww;
}
if(lc>win->cucol || hc>MAX_COL) {
error_msg("Can't find a non-zero-width column in recenter_window()");
/* ... */
}
} else {
lc=hc=win->cucol;
n=totwid=get_width(win->cucol);
do {
if(lc>MIN_COL && totwid+(n=get_width(lc-1))<win->numc) {
--lc;
totwid+=n;
more=1;
} else
more=0;
if(hc<MAX_COL && totwid+(n=get_width(hc+1))<win->numc) {
hc++;
totwid+=n;
more++;
}
} while(more);
}
while(get_width(lc)==0)
lc++;
while(get_width(hc)==0)
--(hc);
win->screen.lc=lc;
win->screen.hc=hc;
win->screen.lr=lr;
win->screen.hr=hr;
}
int
scroll_cell_cursor FUN1(int, magic)
{
int off_dn,off_rt;
int n=0;
int totwid;
struct rng s;
CELLREF cr,cc;
unsigned short w;
int over,down;
over=colmagic[magic]*how_many;
down=rowmagic[magic]*how_many;
if(down) {
off_dn=curow-cwin->screen.lr;
n=down*cwin->numr;
if(n>MAX_ROW-MIN_ROW) {
error_msg(down>0 ? "Can't scroll down" : "Can't scroll up");
return 0;
}
if(down>0) {
if(cwin->screen.lr>MAX_ROW-n) {
error_msg("Can't scroll down");
return 0;
}
if(cwin->screen.hr>MAX_ROW-n) {
s.hr=MAX_ROW;
s.lr= (cwin->win_flags&WIN_PAG_VT) ? cwin->screen.lr+n : 1+s.hr-cwin->numr;
cr= (off_dn>s.hr-s.lr) ? MAX_ROW : s.lr+off_dn;
} else {
s.lr=cwin->screen.lr+n;
s.hr=cwin->screen.hr+n;
cr=s.lr+off_dn;
}
} else {
if(cwin->screen.hr<MIN_ROW-n) {
error_msg("Can't scroll up");
return 0;
}
if((cwin->win_flags&WIN_PAG_VT) && cwin->screen.hr==MAX_ROW) {
s.lr=cwin->screen.lr+n;
s.hr=s.lr+cwin->numr-1;
} else if(cwin->screen.lr<MIN_ROW-n) {
s.lr=MIN_ROW;
s.hr=s.lr+cwin->numr-1;
} else {
s.lr=cwin->screen.lr+n;
s.hr=cwin->screen.hr+n;
}
cr=s.lr+off_dn;
}
set_numcols(cwin,s.hr);
} else {
s.lr=cwin->screen.lr;
s.hr=cwin->screen.hr;
cr=curow;
}
off_rt=cucol-cwin->screen.lc;
if(over>0) {
if(cwin->screen.hc==MAX_COL) {
error_msg("Can't scroll right");
return 0;
}
for(s.lc=s.hc=cwin->screen.hc+1;;s.lc= ++s.hc) {
--over;
totwid=get_width(s.lc);
while(s.hc<MAX_COL && totwid+(n=get_width(s.hc+1))<=cwin->numc) {
s.hc++;
totwid+=n;
}
if(!over || s.hc==MAX_COL)
break;
}
if(!(cwin->win_flags&WIN_PAG_HZ)) {
while(s.lc>MIN_COL && totwid+(n=get_width(s.lc-1))<=cwin->numc) {
s.lc--;
totwid+=n;
off_rt++;
}
}
cc= (s.hc-s.lc<off_rt) ? s.hc : s.lc+off_rt;
} else if(over<0) {
if(cwin->screen.lc==MIN_COL) {
error_msg("Can't scroll left");
return 0;
}
if(cwin->win_flags&WIN_PAG_HZ) {
/* This is tricky! */
int n_over;
unsigned short ww = 0;
n_over=0;
for(s.lc=s.hc=MIN_COL,w=get_width(s.hc);
;
s.lc= ++s.hc,w=ww,n_over++) {
while(s.hc<MAX_COL && w+(ww=get_width(s.hc+1))<=cwin->numc) {
s.hc++;
w+=ww;
}
if(s.hc>=cucol)
break;
}
n_over+=over;
if(n_over<0) {
error_msg("Can't scroll left");
return 0;
}
for(s.lc=s.hc=MIN_COL,w=get_width(s.hc);
;
s.lc=s.hc+1,s.hc++,w=ww) {
ww=get_width(s.hc+1);
while(w+ww<=cwin->numc && s.hc<MAX_COL) {
s.hc++;
w+=ww;
ww=get_width(s.hc+1);
}
if(!n_over--)
break;
}
over=0;
cc= (s.hc-s.lc<off_rt) ? s.hc : s.lc+off_rt;
} else {
for(s.lc=s.hc=cwin->screen.lc-1;;s.hc= --s.lc) {
over++;
totwid=get_width(s.lc);
while(s.lc>MIN_COL && totwid+(n=get_width(s.lc-1))<=cwin->numc) {
s.lc--;
totwid+=n;
}
if(!over || s.lc==MIN_COL)
break;
}
if(s.lc==MIN_COL) {
while(s.hc<MAX_COL && totwid+(n=get_width(s.hc+1))<=cwin->numc) {
s.hc++;
totwid+=n;
}
}
cc= (s.hc-s.lc<off_rt) ? s.lc : s.lc+off_rt;
}
} else if(!(cwin->win_flags&WIN_PAG_HZ)) {
/* If page_scroll, we don't have to bother with this.
It'll fit. That's all. . . */
totwid=0;
s.lc=cwin->screen.lc;
s.hc=cwin->screen.hc;
cc=cucol;
/* This is tricky: ;n<=s.hc; won't work if s.hc==MAX_CELLREF */
for(n=s.lc;;n++) {
totwid+=get_width(n);
if(n==s.hc)
break;
}
while(cwin->numc<totwid) {
if(cucol==s.lc)
totwid-=get_width(s.hc--);
else
totwid-=get_width(s.lc++);
}
while(s.hc<MAX_COL && totwid+(n=get_width(s.hc+1))<=cwin->numc) {
++s.hc;
totwid+=n;
}
while(s.lc>MIN_COL && totwid+(n=get_width(s.lc-1))<=cwin->numc) {
--s.lc;
totwid+=n;
}
} else {
cwin->screen.lr=s.lr;
cwin->screen.hr=s.hr;
if(cwin->win_linked!=-1)
shift_linked_window((long)cr-curow,(long)0);
curow=cr;
disp_scrn();
return 1;
}
if(over) {
error_msg(over>0 ? "Can't scroll right" : "Can't scroll left");
return 0;
}
while(get_width(s.lc)==0)
s.lc++;
while(get_width(s.hc)==0)
--(s.hc);
if(cwin->win_linked!=-1)
shift_linked_window((long)cr-curow,(long)cc-cucol);
cwin->screen=s;
curow=cr;
cucol=cc;
if(get_width(cc)==0)
find_nonzero_width(cwin);
disp_scrn();
return 1;
}
void
read_mp_windows FUN1(char *,line)
{
int wnum=0;
char *text;
CELLREF nrow=NON_ROW,ncol=NON_COL;
char *split=0;
char *opts=0;
struct window *win;
text=line;
for(;;) {
switch(*text++) {
/* Window Number */
case 'N':
wnum=astol(&text);
break;
/* Cursor At */
case 'A':
nrow=astol(&text);
ncol=astol(&text);
break;
/* JF: Window options */
case 'O':
opts=text;
while(*text && *text!=';')
text++;
break;
/* Split into two windows */
case 'S':
split=text;
while(*text && *text!=';')
text++;
break;
/* Set Colors NOT supported */
case 'C':
while(*text && *text!=';')
text++;
break;
/* Alternate border NOT supported. . . */
case 'B':
break;
default:
--text;
break;
}
if(*text=='\0' || *text=='\n')
break;
if(*text!=';') {
char *bad;
bad=text;
while(*text && *text!=';')
text++;
if(*text)
*text++='\0';
error_msg("Unknown SYLK window cmd: %s",bad);
if(!*text)
break;
} else
*text++='\0';
}
if(wnum<1 || wnum>nwin) {
error_msg("Window %d out of range in SYLK line %s",wnum,line);
return;
}
--wnum;
win= &wins[wnum];
if(nrow!=NON_ROW) {
win->curow=nrow;
win->cucol=ncol;
if(win==cwin) {
curow=nrow;
cucol=ncol;
}
recenter_window(win);
}
if(split) {
int hv = 0;
int where;
int link;
struct window *new;
switch(*split++) {
case 'H':
case 'h':
hv=1;
break;
case 'v':
case 'V':
hv=0;
break;
case 't':
case 'T':
error_msg("Window split titles not supported");
return;
default:
break;
}
if(*split=='L') {
link=wnum;
split++;
} else
link= -1;
where=astol(&split);
if(hv ? where>=win->numr : where>=win->numc)
error_msg("Can't split window: screen too small");
nwin++;
wins=ck_realloc(wins,nwin*sizeof(struct window));
cwin=wins;
win= &wins[wnum];
new= &wins[nwin-1];
win->numc-=(hv ? 0 : where);
win->numr-=(hv ? where : 0);
win->curow=curow;
win->cucol=cucol;
new->win_flags = WIN_EDGES|WIN_EDGE_REV;/* Mplan defaults */
new->lh_wid=0; /* For now */
new->win_linked=link;
new->win_over=win->win_over + (hv ? -win->lh_wid : win->numc);
new->win_down=win->win_down + (hv ? win->numr+1 : 0);
new->numc=(hv ? win->numc+win->lh_wid : where);
new->numr=(hv ? where-1 : win->numr);
new->curow=curow;
new->cucol=cucol;
set_numcols(new,curow);
recenter_window(win);
recenter_window(new);
}
if(opts) {
char *np;
while(np=index(opts,',')) {
*np='\0';
set_options(opts);
*np++=';';
opts=np;
}
if(np=rindex(opts,'\n'))
*np='\0';
set_options(opts);
}
}
void
write_mp_windows FUN1(FILE *,fp)
{
int n;
char buf[90];
cwin->curow=curow;
cwin->cucol=cucol;
fprintf(fp,"O;status %d\n",status);
if(nwin>1) {
/* ... */
}
for(n=0;n<nwin;n++) {
buf[0]='\0';
if(wins[n].win_flags&WIN_LCK_HZ)
strcat(buf,",lockh");
if(wins[n].win_flags&WIN_LCK_VT)
strcat(buf,",lockv");
if(wins[n].win_flags&WIN_PAG_HZ)
strcat(buf,",pageh");
if(wins[n].win_flags&WIN_PAG_VT)
strcat(buf,",pagev");
if(wins[n].win_flags&WIN_EDGE_REV)
strcat(buf,",standout");
if((wins[n].win_flags&WIN_EDGES)==0)
strcat(buf,",noedges");
fprintf(fp,"W;N%d;A%u %u;C%d %d %d;O%s\n",n+1,wins[n].curow,wins[n].cucol,7,0,7,buf+1);
}
}